/*
 * Copyright 2008-2013 Freescale Semiconductor, Inc.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdio.h>
#include "flib/rta.h"
#include "test_common.h"

enum rta_sec_era rta_sec_era;

int test_op_cipher(uint32_t *buff)
{
	struct program prg;
	struct program *p = &prg;

	PROGRAM_CNTXT_INIT(p, buff, 0);
	if (need_bswap)
		PROGRAM_SET_BSWAP(p);
	{
/* RNG tests */
		ALG_OPERATION(p, OP_ALG_ALGSEL_RNG, OP_ALG_AAI_RNG, 0, 0, 0);

/* DESA family tests */
		ALG_OPERATION(p, OP_ALG_ALGSEL_DES, OP_ALG_AAI_ECB, 0, 0,
			      DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_DES,
			      OP_ALG_AAI_ECB | OP_ALG_AAI_CHECKODD, 0, 0,
			      DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_3DES, OP_ALG_AAI_CBC, 0, 0,
			      DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_3DES, OP_ALG_AAI_OFB, 0, 0,
			      DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_DES, OP_ALG_AAI_CFB, 0, 0,
			      DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_3DES, OP_ALG_AAI_OFB,
			      OP_ALG_AS_INITFINAL, 0, DIR_ENC);

/* AESA family tests */
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_ECB, 0, 0,
			      DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CBC, 0, 0,
			      DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CBC,
			      OP_ALG_AS_INIT, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_3DES, OP_ALG_AAI_CBC,
			      OP_ALG_AS_INITFINAL, 0, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
			      OP_ALG_AAI_CBC | OP_ALG_AAI_DK, 0, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CCM,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_GCM,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
			      OP_ALG_AAI_CCM | OP_ALG_AAI_C2K,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
			      OP_ALG_AAI_GCM | OP_ALG_AAI_C2K,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XTS,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR_XCBCMAC,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CBC_XCBCMAC,
			      OP_ALG_AS_INITFINAL, 0, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CMAC,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CBC_CMAC,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR_CMAC,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR_CMAC_LTE,
			      OP_ALG_AS_INITFINAL, 0, DIR_ENC);

/* Kasumi family tests */
		ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F8,
			      OP_ALG_AS_INITFINAL, 0, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_GSM,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_EDGE,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F9,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_ENC);

/* SNOW 3G family tests */
		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
			      OP_ALG_AS_INITFINAL, 0, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_ENC);

/* ARC4 family tests */
		ALG_OPERATION(p, OP_ALG_ALGSEL_ARC4, 0, OP_ALG_AS_INIT, 0,
			      DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_ARC4, 0, OP_ALG_AS_INIT, 0,
			      DIR_DEC);

		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, OP_ALG_AAI_F9,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, OP_ALG_AAI_F9,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, OP_ALG_AAI_F9,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);

/* CRC family tests */
		ALG_OPERATION(p, OP_ALG_ALGSEL_CRC,
			      OP_ALG_AAI_802 | OP_ALG_AAI_DIS |
				   OP_ALG_AAI_DOS | OP_ALG_AAI_DOC |
				   OP_ALG_AAI_IVZ, OP_ALG_AS_INITFINAL,
			      ICV_CHECK_ENABLE, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_CRC,
			      OP_ALG_AAI_3385 | OP_ALG_AAI_DIS |
				   OP_ALG_AAI_DOS | OP_ALG_AAI_DOC |
				   OP_ALG_AAI_IVZ, OP_ALG_AS_UPDATE,
			      ICV_CHECK_ENABLE, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_CRC,
			      OP_ALG_AAI_CUST_POLY | OP_ALG_AAI_DIS |
				   OP_ALG_AAI_DOS | OP_ALG_AAI_DOC |
				   OP_ALG_AAI_IVZ, OP_ALG_AS_INIT,
			      ICV_CHECK_ENABLE, DIR_DEC);
	}

	return PROGRAM_FINALIZE(p);
}

int test_op_alg_mdha(uint32_t *buff)
{
	struct program prg;
	struct program *p = &prg;

	PROGRAM_CNTXT_INIT(p, buff, 0);
	if (need_bswap)
		PROGRAM_SET_BSWAP(p);
	{
/* MDHA family tests */
		ALG_OPERATION(p, OP_ALG_ALGSEL_MD5, OP_ALG_AAI_HASH,
			      OP_ALG_AS_INIT, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA1, OP_ALG_AAI_HASH,
			      OP_ALG_AS_UPDATE, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA224, OP_ALG_AAI_HASH,
			      OP_ALG_AS_FINALIZE, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA256, OP_ALG_AAI_HASH, 0, 0,
			      DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA384, OP_ALG_AAI_HASH,
			      OP_ALG_AS_INITFINAL, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA384, OP_ALG_AAI_HASH,
			      OP_ALG_AS_INITFINAL, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA512, OP_ALG_AAI_HASH,
			      OP_ALG_AS_INITFINAL, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_MD5, OP_ALG_AAI_SMAC,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA1, OP_ALG_AAI_SMAC,
			      OP_ALG_AS_UPDATE, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_MD5, OP_ALG_AAI_HMAC,
			      OP_ALG_AS_INIT, 0, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA1, OP_ALG_AAI_HMAC,
			      OP_ALG_AS_UPDATE, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA224, OP_ALG_AAI_HMAC,
			      OP_ALG_AS_FINALIZE, ICV_CHECK_ENABLE, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA256, OP_ALG_AAI_HMAC, 0, 0,
			      0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA384, OP_ALG_AAI_HMAC,
			      OP_ALG_AS_INITFINAL, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA384, OP_ALG_AAI_HMAC,
			      OP_ALG_AS_INITFINAL, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA512, OP_ALG_AAI_HMAC,
			      OP_ALG_AS_INITFINAL, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_MD5, OP_ALG_AAI_HMAC_PRECOMP,
			      OP_ALG_AS_INIT, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA1, OP_ALG_AAI_HMAC_PRECOMP,
			      OP_ALG_AS_UPDATE, 0, DIR_ENC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA224, OP_ALG_AAI_HMAC_PRECOMP,
			      OP_ALG_AS_FINALIZE, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA256, OP_ALG_AAI_HMAC_PRECOMP,
			      0, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA384, OP_ALG_AAI_HMAC_PRECOMP,
			      OP_ALG_AS_INITFINAL, 0, 0);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA512, OP_ALG_AAI_HMAC_PRECOMP,
			      OP_ALG_AS_INITFINAL, 0, DIR_DEC);
		ALG_OPERATION(p, OP_ALG_ALGSEL_SHA384, OP_ALG_AAI_HMAC_PRECOMP,
			      OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, 0);
	}

	return PROGRAM_FINALIZE(p);
}

uint32_t prg_buff[1000];

int main(int argc, char **argv)
{
	int size;

	rta_set_sec_era(RTA_SEC_ERA_5);

	pr_debug("OPERATION ALGORITHM CIPHER program\n");
	size = test_op_cipher(prg_buff);
	pr_debug("size = %d\n", size);
	print_prog(prg_buff, size);

	pr_debug("OPERATION ALGORITHM MDHA program\n");
	size = test_op_alg_mdha(prg_buff);
	pr_debug("size = %d\n", size);
	print_prog(prg_buff, size);

	return 0;
}
